package com.alks.function.service.impl.biocontrol.deptwork;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.enums.factoryquery.PcProcessEnum;
import com.alks.entity.data.page.PageParam;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.request.biocontrol.deptwork.KpiPersonRequest;
import com.alks.function.data.request.biocontrol.deptwork.ProdMonthRequest;
import com.alks.function.mapper.biocontrol.deptwork.*;
import com.alks.function.service.biocontrol.deptwork.IProdTagService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.INPUT_ERROR;
import static com.alks.entity.data.enums.ResultCodeEnum.IN_IS_EMPTY;

@Service
@Slf4j
@RequiredArgsConstructor
public class ProdTagServiceImpl extends ServiceImpl<BC_DW_PcProdTotalMonthMapper, PcProdTotalMonth> implements IProdTagService {
    private final BC_DW_PcProdTotalMonthMapper monthMapper;
    private final BC_DW_PcProdTotalWeekMapper weekMapper;
    private final BC_DW_PcProdTotalWeekTargetMapper weekTargetMapper;
    private final BC_DW_PcProdTotalPpdMapper ppdMapper;
    private final BC_DW_PcKpiDeptPersonsMapper personsMapper;
    private final BC_DW_PcMonthHolidayMapper holidayMapper;

    @Override
    @AutoPageAop
    public ResponseInfo getProdMonthQuery(PageParam request, LocalDateTime month, String deptFlag) {
        /*获取数据*/
        List<PcProdTotalMonth> dtos = lambdaQuery()
                .eq(PcProdTotalMonth::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalMonth::getMonth, month.format(DateTimeFormatter.ofPattern("yyyyMM")))
                .eq(deptFlag.equals("N"), PcProdTotalMonth::getDeptFlag, "Y")
                .orderByAsc(PcProdTotalMonth::getSeqNo).list();
        Page<PcProdTotalMonth> page = (Page<PcProdTotalMonth>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("dtos", dtos);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo prodMonthAdd(ProdMonthRequest request) {
        /*入参判断 月份,序号不能为空或者重复*/
        if (request.getMonth() == null && request.getSeqNo() == null) {
            return ResponseInfo.error("月份和序号不能为空", INPUT_ERROR.getCode());
        }
        Integer count = lambdaQuery().eq(PcProdTotalMonth::getMonth, request.getMonth())
                .eq(PcProdTotalMonth::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalMonth::getSeqNo, request.getSeqNo()).count();
        if (count > 0) {
            return ResponseInfo.error("相同月份中序号不能重复", INPUT_ERROR.getCode());
        }
        /*获取待写入数据*/
        PcProdTotalMonth month = BeanUtil.copyBean(request, PcProdTotalMonth.class);
        month.setCompanyId(UserIdThread.get().getCompanyId());
        monthMapper.insert(month);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo prodMonthUp(ProdMonthRequest request, String monthOld, String seqNoOld) {
        /*入参判断 月份,序号不能为空或者重复*/
        if (request.getMonth().isEmpty() && request.getSeqNo() == null) {
            return ResponseInfo.error("月份和序号不能为空", INPUT_ERROR.getCode());
        }
        Integer count = lambdaQuery().eq(PcProdTotalMonth::getMonth, request.getMonth())
                .eq(PcProdTotalMonth::getSeqNo, request.getSeqNo()).count();
        if (!monthOld.equals(request.getMonth()) && count > 0) {
            return ResponseInfo.error("相同月份中序号不能重复", INPUT_ERROR.getCode());
        }
        /*更新数据*/
        PcProdTotalMonth month = BeanUtil.copyBean(request, PcProdTotalMonth.class);
        month.setCompanyId(UserIdThread.get().getCompanyId());
        LambdaUpdateWrapper<PcProdTotalMonth> wrapper = new LambdaUpdateWrapper<PcProdTotalMonth>()
                .eq(PcProdTotalMonth::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalMonth::getMonth, monthOld)
                .eq(PcProdTotalMonth::getSeqNo, seqNoOld)
                .set(request.getSeqNo() == null, PcProdTotalMonth::getSeqNo, null)
                .set(request.getDeptType() == null, PcProdTotalMonth::getDeptType, null)
                .set(request.getDeptNo() == null, PcProdTotalMonth::getDeptNo, null)
                .set(request.getDeptName() == null, PcProdTotalMonth::getDeptName, null)
                .set(request.getDutyPerson() == null, PcProdTotalMonth::getDutyPerson, null)
                .set(request.getDeptFlag() == null, PcProdTotalMonth::getDeptFlag, null)
                .set(request.getLevelCode() == null, PcProdTotalMonth::getLevelCode, null)
                .set(request.getParentDept() == null, PcProdTotalMonth::getParentDept, null)
                .set(request.getMonthTarget() == null, PcProdTotalMonth::getMonthTarget, null)
                .set(request.getWorkDays() == null, PcProdTotalMonth::getWorkDays, null);
        monthMapper.update(month, wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo prodMonthDelete(String month, String seqNo) {
        /*删除数据*/
        LambdaQueryWrapper<PcProdTotalMonth> wrapper = new LambdaQueryWrapper<PcProdTotalMonth>()
                .eq(PcProdTotalMonth::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalMonth::getMonth, month)
                .eq(PcProdTotalMonth::getSeqNo, seqNo);
        monthMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo getProdWeekQuery() {
        /*获取数据*/
        LambdaQueryWrapper<PcProdTotalWeek> wrapper = new LambdaQueryWrapper<PcProdTotalWeek>()
                .eq(PcProdTotalWeek::getCompanyId, UserIdThread.get().getCompanyId());
        List<PcProdTotalWeek> dtos = weekMapper.selectList(wrapper);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo getProTarDefQuery() {
        /*获取数据*/
        LambdaQueryWrapper<PcProdTotalWeekTarget> wrapper = new LambdaQueryWrapper<PcProdTotalWeekTarget>()
                .eq(PcProdTotalWeekTarget::getCompanyId, UserIdThread.get().getCompanyId());
        List<PcProdTotalWeekTarget> dtos = weekTargetMapper.selectList(wrapper);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo proTarDefAdd(String deptName, BigDecimal weekTargetQty) {
        /*新增数据*/
        PcProdTotalWeekTarget target = new PcProdTotalWeekTarget();
        target.setCompanyId(UserIdThread.get().getCompanyId());
        target.setDeptName(deptName);
        target.setWeekTargetQty(weekTargetQty);
        weekTargetMapper.insert(target);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo proTarDefUpdate(PcProdTotalWeekTarget request, String deptNameOld, String weekTargetQtyOld) {
        /*更新数据*/
        LambdaQueryWrapper<PcProdTotalWeekTarget> wrapper = new LambdaQueryWrapper<PcProdTotalWeekTarget>()
                .eq(PcProdTotalWeekTarget::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalWeekTarget::getDeptName, deptNameOld)
                .eq(PcProdTotalWeekTarget::getWeekTargetQty, weekTargetQtyOld);
        request.setCompanyId(UserIdThread.get().getCompanyId());
        weekTargetMapper.update(request, wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo proTarDefDelete(String deptName, String weekTargetQty) {
        /*删除数据*/
        LambdaQueryWrapper<PcProdTotalWeekTarget> wrapper = new LambdaQueryWrapper<PcProdTotalWeekTarget>()
                .eq(PcProdTotalWeekTarget::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcProdTotalWeekTarget::getDeptName, deptName)
                .eq(PcProdTotalWeekTarget::getWeekTargetQty, weekTargetQty);
        weekTargetMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo getProdPersonQuery() {
        /*获取数据*/
        LambdaQueryWrapper<PcProdTotalPpd> wrapper = new LambdaQueryWrapper<PcProdTotalPpd>()
                .eq(PcProdTotalPpd::getCompanyId, UserIdThread.get().getCompanyId());
        List<PcProdTotalPpd> dtos = ppdMapper.selectList(wrapper);
        return ResponseInfo.ok(dtos);
    }

    @Override
    @AutoPageAop
    public ResponseInfo getkpiPersonQuery(KpiPersonRequest request) {
        /*获取数据*/
        LambdaQueryWrapper<PcKpiDeptPersons> wrapper = new LambdaQueryWrapper<PcKpiDeptPersons>()
                .eq(PcKpiDeptPersons::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(request.getFactoryDept() != null && !request.getFactoryDept().isEmpty(), PcKpiDeptPersons::getFactoryDept, request.getFactoryDept())
                .like(request.getDeptType() != null && !request.getDeptType().isEmpty(), PcKpiDeptPersons::getDeptType, request.getDeptType())
                .like(request.getDeptName() != null && !request.getDeptName().isEmpty(), PcKpiDeptPersons::getDeptName, request.getDeptName())
                .ge(request.getDdateStart() != null, PcKpiDeptPersons::getDdate, request.getDdateStart())
                .le(request.getDdateEnd() != null, PcKpiDeptPersons::getDdate, request.getDdateEnd())
                .orderByDesc(PcKpiDeptPersons::getDdate);
        List<PcKpiDeptPersons> dtos = personsMapper.selectList(wrapper);
        Page<PcKpiDeptPersons> page = (Page<PcKpiDeptPersons>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("dtos", dtos);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo kpiPersonAdd(PcKpiDeptPersons request) {
        /*检测入参合法性*/
        if (request.getDeptType() == null || request.getDeptName() == null || request.getDdate() == null) {
            return ResponseInfo.error("必要参数为空", INPUT_ERROR.getCode());
        }
        LambdaQueryWrapper<PcKpiDeptPersons> wrapper = new LambdaQueryWrapper<PcKpiDeptPersons>()
                .eq(PcKpiDeptPersons::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcKpiDeptPersons::getDeptType, request.getDeptType())
                .eq(PcKpiDeptPersons::getDeptName, request.getDeptName())
                .eq(PcKpiDeptPersons::getDdate, request.getDdate());
        if (personsMapper.selectCount(wrapper) > 0) {
            return ResponseInfo.error("存在相同数据", INPUT_ERROR.getCode());
        }
        /*补充数据*/
        request.setDeptNo(request.getDeptName());
        request.setCompanyId(UserIdThread.get().getCompanyId());
        request.setSysDate(LocalDateTime.now());
        request.setSysUser(UserIdThread.get().getUserName());
        /*写入数据*/
        personsMapper.insert(request);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo kpiPersonUp(PcKpiDeptPersons request, String deptTypeOld, String deptNameOld, LocalDate dDateOld) {        /*检测入参合法性*/
        /*检测入参合法性*/
        if (request.getDeptType() == null || request.getDeptName() == null || request.getDdate() == null) {
            return ResponseInfo.error("必要参数为空", INPUT_ERROR.getCode());
        }
        LambdaQueryWrapper<PcKpiDeptPersons> wrapper1 = new LambdaQueryWrapper<PcKpiDeptPersons>()
                .eq(PcKpiDeptPersons::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcKpiDeptPersons::getDeptType, request.getDeptType())
                .eq(PcKpiDeptPersons::getDeptName, request.getDeptName())
                .eq(PcKpiDeptPersons::getDdate, request.getDdate());
        if (personsMapper.selectCount(wrapper1) > 0) {
            return ResponseInfo.error("存在相同数据", INPUT_ERROR.getCode());
        }
        /*补充数据*/
        request.setDeptNo(request.getDeptName());
        request.setCompanyId(UserIdThread.get().getCompanyId());
        request.setSysDate(LocalDateTime.now());
        request.setSysUser(UserIdThread.get().getUserName());
        /*更新数据*/
        LambdaQueryWrapper<PcKpiDeptPersons> wrapper2 = new LambdaQueryWrapper<PcKpiDeptPersons>()
                .eq(PcKpiDeptPersons::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcKpiDeptPersons::getDeptType, deptTypeOld)
                .eq(PcKpiDeptPersons::getDeptName, deptNameOld)
                .eq(PcKpiDeptPersons::getDdate, dDateOld);
        personsMapper.update(request, wrapper2);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo kpiPersonDelete(String deptType, String deptName, LocalDate dDate) {
        /*删除数据*/
        LambdaQueryWrapper<PcKpiDeptPersons> wrapper = new LambdaQueryWrapper<PcKpiDeptPersons>()
                .eq(PcKpiDeptPersons::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcKpiDeptPersons::getDeptType, deptType)
                .eq(PcKpiDeptPersons::getDeptName, deptName)
                .eq(PcKpiDeptPersons::getDdate, dDate);
        personsMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @AutoPageAop
    public ResponseInfo getMonthHolidayQuery(PageParam request, LocalDate dDate) {
        if (dDate == null) {
            dDate = LocalDate.now();
        }
        /*获取数据*/
        LambdaQueryWrapper<PcMonthHoliday> wrapper = new LambdaQueryWrapper<PcMonthHoliday>()
                .eq(PcMonthHoliday::getCompanyId, UserIdThread.get().getCompanyId())
                .ge(PcMonthHoliday::getDdate, dDate);
        List<PcMonthHoliday> holidays = holidayMapper.selectList(wrapper);
        List<String> dtos = holidays.stream().map(a -> a.getDdate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                .collect(Collectors.toList());
        Page<PcMonthHoliday> page = (Page<PcMonthHoliday>) holidays;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("dtos", dtos);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public ResponseInfo MonthHolidayAdd(LocalDate dDate) {
        /*入参判断*/
        if (dDate == null) {
            return ResponseInfo.error("时间不能为空", IN_IS_EMPTY.getCode());
        }
        /*写入数据*/
        PcMonthHoliday holiday = new PcMonthHoliday();
        holiday.setDdate(dDate.atStartOfDay());
        holiday.setCompanyId(UserIdThread.get().getCompanyId());
        /*新增*/
        holidayMapper.insert(holiday);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo MonthHolidayUp(LocalDate dDate, LocalDate dDateOld) {
        /*入参判断*/
        if (dDate == null) {
            return ResponseInfo.error("时间不能为空", IN_IS_EMPTY.getCode());
        }
        /*写入数据*/
        LambdaUpdateWrapper<PcMonthHoliday> wrapper = new LambdaUpdateWrapper<PcMonthHoliday>()
                .eq(PcMonthHoliday::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcMonthHoliday::getDdate, dDate)
                .set(PcMonthHoliday::getDdate, dDateOld)
                .last("LIMIT 1");
        holidayMapper.update(null, wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo MonthHolidayDelete(LocalDate dDate) {
        /*删除数据*/
        LambdaQueryWrapper<PcMonthHoliday> wrapper = new LambdaQueryWrapper<PcMonthHoliday>()
                .eq(PcMonthHoliday::getCompanyId, UserIdThread.get().getCompanyId())
                .eq(PcMonthHoliday::getDdate, dDate)
                .last("LIMIT 1");
        holidayMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo prodUpdate(LocalDateTime month) {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取月份区间*/

        /*获取月生产量数据*/

        /*获取周区间*/

        /*获取周生产数据*/

        /*计算人均产能数据*/

        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo MonthDeptType() {
        /*获取数据*/
        List<String> dtos = PcProcessEnum.getNameList();
        return ResponseInfo.ok(dtos);
    }

    @Override
    public void lastMonthUp(LocalDateTime month, LocalDateTime tagMonth) {
        String companyId = UserIdThread.get().getCompanyId();
        /*入参格式化*/
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMM");
        String mt = month.format(formatter);
        String tmt = tagMonth.format(formatter);
        if (StringUtils.isBlank(tmt)) {
            /*获取最近的月份*/
            PcProdTotalMonth totalMonth = lambdaQuery()
                    .eq(PcProdTotalMonth::getCompanyId, companyId)
                    .orderByDesc(PcProdTotalMonth::getMonth)
                    .last("LIMIT 1").one();
            if (totalMonth == null) {
                return;
            }
            tmt = totalMonth.getMonth();
        }
        /*获取数据*/
        List<PcProdTotalMonth> totalMonthList = lambdaQuery()
                .eq(PcProdTotalMonth::getMonth, tmt)
                .eq(PcProdTotalMonth::getCompanyId, companyId).list();
        /*获取当月天数*/
        int monthLength = DateUtils.getLengthOfMonth(month);
        /*获取放假日期*/
        LambdaQueryWrapper<PcMonthHoliday> holidayWrapper = new LambdaQueryWrapper<PcMonthHoliday>()
                .ge(PcMonthHoliday::getDdate, DateUtils.getFirstDayOfMonth(month))
                .le(PcMonthHoliday::getDdate, DateUtils.getLastDayOfMonth(month))
                .eq(PcMonthHoliday::getCompanyId,companyId);
        Integer holidayCount = holidayMapper.selectCount(holidayWrapper);
        /*获取周日数*/
        int sundayCount = DateUtils.getSundayCount(month);
        /*获取最终工作天数*/
        int workDay = monthLength - holidayCount - sundayCount;
        for (PcProdTotalMonth totalMonth : totalMonthList) {
            LocalDate monthLocalDate = month.toLocalDate();
            /*更新数据*/
            totalMonth.setMonth(mt);
            totalMonth.setWorkDays(BigDecimal.valueOf(workDay));
            if (totalMonth.getMonthTarget().compareTo(BigDecimal.ZERO)>0){
                BigDecimal dayTarget = totalMonth.getMonthTarget().divide(BigDecimal.valueOf(workDay), 0, RoundingMode.HALF_UP);
                totalMonth.setDayTarget(dayTarget);
            }
            monthMapper.insert(totalMonth);
        }
    }
}
